package com.fy56.platform.logistics.websocket;

import com.alibaba.fastjson.JSON;
import com.fy56.platform.logistics.websocket.cache.SessionCache;
import com.fy56.platform.logistics.websocket.messages.ConnectionInfoMessage;
import com.fy56.platform.logistics.websocket.messages.MessageInfoMessage;
import com.fy56.platform.logistics.websocket.messages.StatusInfoMessage;
import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.WsOutbound;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2015/8/22.
 */
public class SocketConnection extends MessageInbound {

    private static final Logger LOGGER = LoggerFactory.getLogger(SocketConnection.class);

    private final String connectionId;

    private final String userName;

    private final String tag;


    public SocketConnection(String connectionId, String userName,String tag) {
        this.connectionId = connectionId;
        this.userName = userName;
        this.tag=tag;
    }

    @Override
    protected void onOpen(WsOutbound outbound) {
        System.out.println("+++++++++++++新加入的session++++++++++++++++++++");
        SessionCache.connections.put(connectionId, this);
        System.out.println("session:"+connectionId+" user:"+this.getUserName());
        System.out.println("+++++++++++++新加入session后的缓存值 ++++++++++++++++++++ 总数:"+ SessionCache.connections.size());
        for(Map.Entry<String,SocketConnection> entry:SessionCache.connections.entrySet()){
            System.out.println("session:"+entry.getKey()+" user:"+entry.getValue().getUserName()+" tag:"+entry.getValue().getTag());
        }
        System.out.println("+++++++++++++++++++++++++++++++++");
    }

    private void sendConnectionInfo(WsOutbound outbound) {
        final List<String> activeUsers = getActiveUsers();
        final ConnectionInfoMessage connectionInfoMessage = new ConnectionInfoMessage(userName, activeUsers);
        try {
            outbound.writeTextMessage(CharBuffer.wrap(JSON.toJSONString(connectionInfoMessage)));
        } catch (IOException e) {
            LOGGER.error("Impossible to send message", e);
        }

    }

    @Override
    protected void onClose(int status) {
        if(SessionCache.connections.containsKey(connectionId)) {
            SessionCache.connections.remove(connectionId);
        }

    }

    private void sendStatusInfoToOtherUsers(StatusInfoMessage message) {
        final Collection<SocketConnection> otherUsersConnections = getAllChatConnectionsExceptThis();
        for (SocketConnection chatConnection : otherUsersConnections) {
            try {
                chatConnection.getWsOutbound().writeTextMessage(CharBuffer.wrap(JSON.toJSONString(message)));
            } catch (IOException e) {
                LOGGER.error("Could not send the message", e);
            }
        }
    }

    @Override
    protected void onBinaryMessage(ByteBuffer byteBuffer) throws IOException {
        throw new UnsupportedOperationException("No support binary messages");
    }

    @Override
    protected void onTextMessage(CharBuffer charBuffer) throws IOException {
        final MessageInfoMessage message = JSON.parseObject(charBuffer.toString(), MessageInfoMessage.class);
        final SocketConnection destinationConnection = getDestinationUserConnection(message.getMessageInfo().getTo());
        if (destinationConnection != null) {
            final CharBuffer jsonMessage = CharBuffer.wrap(JSON.toJSONString(message));
            destinationConnection.getWsOutbound().writeTextMessage(jsonMessage);
        } else {
            LOGGER.warn("Trying to send message to user not connected");
        }
    }

    private SocketConnection getDestinationUserConnection(String destinationUser) {
        for (SocketConnection connection : SessionCache.connections.values()) {
            if (destinationUser.equals(connection.getUserName())) {
                return connection;
            }
        }
        return null;
    }

    public Collection<SocketConnection> getAllChatConnectionsExceptThis() {
        final Collection<SocketConnection> allConnections = SessionCache.connections.values();
        allConnections.remove(this);
        return allConnections;
    }

    private List<String> getActiveUsers() {
        final List<String> activeUsers = new ArrayList<String>();
        for (SocketConnection chatConnection : SessionCache.connections.values()) {
            activeUsers.add(chatConnection.getUserName());
        }
        return activeUsers;
    }

    public String getConnectionId() {
        return connectionId;
    }

    public String getUserName() {
        return userName;
    }

    public String getTag() {
        return tag;
    }
}
